home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 June / SGI Freeware 1998 June.iso / dist / fw_UMINNgopher.idb / usr / freeware / src / gopher_1.12 / object / util.c.z / util.c
C/C++ Source or Header  |  1997-09-09  |  11KB  |  514 lines

  1. /********************************************************************
  2.  * $Author: drich $
  3.  * $Revision: 1.1 $
  4.  * $Date: 1995/10/03 04:09:59 $
  5.  * $Source: /proj/freeware1.0/gopher1.12/src/object/RCS/util.c,v $
  6.  * $State: Exp $
  7.  *
  8.  * Paul Lindner, University of Minnesota CIS.
  9.  *
  10.  * Copyright 1991, 1992 by the Regents of the University of Minnesota
  11.  * see the file "Copyright" in the distribution for conditions of use.
  12.  *********************************************************************
  13.  * MODULE: util.c
  14.  * Various useful utilities for gopher clients and servers
  15.  *********************************************************************
  16.  * Revision History:
  17.  * $Log: util.c,v $
  18.  * Revision 1.1  1995/10/03  04:09:59  drich
  19.  * gopher 1.2 check-in
  20.  *
  21.  * Revision 2.4  1993/01/12  21:12:23  lindner
  22.  * Reverted to old readfield behavior()  \n is now ignored again.
  23.  *
  24.  * Revision 2.3  1993/01/08  23:29:21  lindner
  25.  * More mods from jqj.
  26.  *
  27.  * Revision 2.2  1992/12/31  04:58:41  lindner
  28.  * merged 1.1.1.1 and 2.1
  29.  *
  30.  * Revision 2.1  1992/12/21  19:41:14  lindner
  31.  * Added check for null in writestring
  32.  * Added function skip_whitespace
  33.  *
  34.  * Revision 1.1.1.1  1992/12/31  04:52:01  lindner
  35.  * Changes for VMS
  36.  *
  37.  * Revision 1.1  1992/12/10  23:27:52  lindner
  38.  * gopher 1.1 release
  39.  *
  40.  *
  41.  *********************************************************************/
  42.  
  43. #include "Malloc.h"
  44. #include "String.h"
  45. #include <ctype.h>
  46. #include "boolean.h"
  47. #include "util.h"
  48.  
  49. #if defined(VMS) && defined(UCX)
  50. #include <errno.h>
  51. #endif
  52.  
  53. #if defined(VMS) && (defined(WOLLONGONG) || defined(MULTINET))
  54. /* Multinet and Wollongong (non UCX-emulation) use channel numbers */
  55. /* for sockets, which are small multiples of 16.  The first 5 */
  56. /* channels can be assumed to be already used, so we assume that */
  57. /* sockets start at 64, and that only 64 VAXC fds are simultaneously */
  58. /* open in the program.  Actually, the first socket is likely to be */
  59. /* more like 176! */
  60. #define IS_SOCKET(s) ((s)>=64)
  61.  
  62. /* Close a socket.  
  63.  * Note that in old Wollongong and Multinet implementations close()
  64.  * works only on fds, not sockets.
  65.  * For UCX and Unix, closenet() is #defined to be close()
  66.  */
  67. int closenet(s)
  68. int s;
  69. {
  70.     if (IS_SOCKET(s)) {
  71. #ifdef MULTINET
  72.     return (socket_close(s));
  73. #else /* WOLLONGONG */
  74.     return (netclose(s));
  75. #endif
  76.     }
  77.     else
  78.     close(s); /* shouldn't be calling this routine */
  79. }
  80. #endif /* WOLLANGONG or MULTINET */
  81.  
  82.  
  83. /* Read "n" bytes from a descriptor.
  84.  * Use in place of read() when fd is a stream socket
  85.  *
  86.  * Returns the number of total bytes read.
  87.  */
  88.  
  89. int readn(fd, ptr, nbytes)
  90.   int fd;
  91.   char *ptr;
  92.   int nbytes;
  93. {
  94.      int nleft, nread;
  95.      
  96.      nleft = nbytes;
  97.      while (nleft > 0) {
  98. #if defined(VMS) && defined(WOLLONGONG)
  99.       nread = IS_SOCKET(fd) ? netread(fd, ptr, nleft) : read(fd, ptr, nleft);
  100. #else
  101. #if defined(VMS) && defined(MULTINET)
  102.       nread = IS_SOCKET(fd) ? socket_read(fd, ptr, nleft) : read(fd, ptr, nleft);
  103. #else
  104.       nread = read(fd, ptr, nleft);
  105. #endif
  106. #endif
  107. #if defined(VMS) && defined(UCX)
  108.           if (nread < 0 && errno == EPIPE)
  109.            break;
  110. #endif
  111.       if (nread < 0)
  112.            return(nread);    /* error, return <0 */
  113.       else if (nread == 0)    /* EOF */
  114.            break;
  115.       
  116.       nleft     -= nread;
  117.       ptr     += nread;
  118.      }
  119.      return(nbytes - nleft);    /* return >= 0) */
  120. }
  121.  
  122.  
  123.  
  124. /*
  125.  * Write "n" bytes to a descriptor.
  126.  * Use in place of write() when fd is a stream socket
  127.  *
  128.  * We return the number of bytes written
  129.  */
  130.  
  131. int 
  132. writen(fd, ptr, nbytes)
  133.   int    fd;
  134.   char    *ptr;
  135.   int    nbytes;
  136. {
  137.      int nleft, nwritten;
  138.      
  139.      nleft = nbytes;
  140.      while(nleft > 0) {
  141. #if defined(VMS) && defined(WOLLONGONG)
  142.       nwritten = IS_SOCKET(fd) ? netwrite(fd, ptr, nleft) : write(fd, ptr, nleft);
  143. #else
  144. #if defined(VMS) && defined(MULTINET)
  145.       nwritten = IS_SOCKET(fd) ? socket_write(fd, ptr, nleft) : write(fd, ptr, nleft);
  146. #else
  147.       nwritten = write(fd, ptr, nleft);
  148. #endif
  149. #endif
  150.       if (nwritten <= 0)
  151.            return(nwritten);    /* error */
  152.       
  153.       nleft    -= nwritten;
  154.       ptr    += nwritten;
  155.      }
  156.      return(nbytes - nleft);
  157. }
  158.  
  159.  
  160. /*
  161.  * Writestring uses the writen and strlen calls to write a
  162.  * string to the file descriptor fd.  If the write fails
  163.  * a -1 is returned. Otherwise zero is returned.
  164.  */
  165.  
  166. int writestring(fd, stringptr)
  167.   int    fd;
  168.   char    *stringptr;
  169. {
  170.      int length;
  171.  
  172.      if (stringptr == NULL)
  173.       return(0);
  174.  
  175.      length = strlen(stringptr);
  176.      if (writen(fd, stringptr, length) != length) {
  177.       return(-1);
  178.      }
  179.      else
  180.       return(0);
  181. }
  182.  
  183. /*
  184.  * Read from the socket into a buffer.  Mucho more efficent in terms of
  185.  * system calls..
  186.  */
  187.  
  188. #define RECVSIZE 4096
  189.  
  190. static int readrecvbuf(sockfd, buf, len)
  191.   int sockfd;
  192.   char *buf;
  193.   int len;
  194. {
  195.      static char recvbuf[RECVSIZE];
  196.      static int  recvbufptr  = 0;
  197.      static int  recvbufsize = 0;
  198.      static int Oldsockfd = 0;
  199.      int bytesread = 0;
  200.  
  201.      if (recvbufptr == 0 || Oldsockfd != sockfd) {
  202. #if defined(VMS) && defined(WOLLONGONG)
  203.       recvbufsize = IS_SOCKET(sockfd) ?
  204.         netread(sockfd, recvbuf, RECVSIZE) : read(sockfd, recvbuf, RECVSIZE);
  205. #else
  206. #if defined(VMS) && defined(MULTINET)
  207.       recvbufsize = IS_SOCKET(sockfd) ?
  208.         socket_read(sockfd, recvbuf, RECVSIZE) : read(sockfd, recvbuf, RECVSIZE);
  209. #else
  210.       recvbufsize = read(sockfd, recvbuf, RECVSIZE);
  211. #endif
  212. #endif
  213.       Oldsockfd = sockfd;
  214.       recvbufptr = 0;
  215.       if (recvbufsize == 0)
  216.            return(0);
  217. #if defined(VMS) && defined(UCX)
  218.       if (recvbufsize < 0 && errno == EPIPE)
  219.            return(0);
  220. #endif
  221.  
  222.      }
  223.      
  224.      while (len--) {
  225.       *buf++ = recvbuf[recvbufptr++];
  226.       bytesread++;
  227.  
  228.       if (recvbufptr == recvbufsize && len != 0) {
  229.            recvbufsize = readn(sockfd, recvbuf, RECVSIZE);
  230.            recvbufptr = 0;
  231.            if (recvbufsize == 0)
  232.             return(bytesread);
  233.            if (recvbufsize < 0)
  234.             return(recvbufsize);
  235.  
  236.       } else if (recvbufptr >= recvbufsize)
  237.            recvbufptr = 0;
  238.      }
  239.      return(bytesread);
  240. }     
  241.  
  242.  
  243. /*
  244.  * Read a line from a descriptor.  Read the line one byte at a time,
  245.  * looking for the newline.  We store the newline in the buffer,
  246.  * then follow it with a null (the same as fgets(3)).
  247.  * We return the number of characters up to, but not including,
  248.  * the null (the same as strlen(3))
  249.  */
  250.  
  251. int readline(fd, ptr, maxlen)
  252.   int    fd;
  253.   char    *ptr;
  254.   int     maxlen;
  255. {
  256.      int n;
  257.      int rc;
  258.      char c;
  259.  
  260.      
  261.      for (n=1; n < maxlen; n++) {
  262.       if ( (rc = readrecvbuf(fd, &c, 1)) == 1) {
  263.            *ptr++ = c;
  264.            if (c == '\n')
  265.             break;
  266.       }
  267.       else if (rc == 0) {
  268.            if (n == 1)
  269.             return(0);    /* EOF, no data read */
  270.            else
  271.             break;        /* EOF, some data was read */
  272.       }
  273.       else
  274.            return(-1);        /* error */
  275.      }
  276.      
  277.      *ptr = 0;                 /* Tack a NULL on the end */
  278.      return(n);
  279. }
  280.  
  281. /*
  282.  * Readfield reads data up to a tab, (like readline above)
  283.  */
  284.  
  285. int 
  286. readfield(fd, ptr, maxlen)
  287.   int    fd;
  288.   char    *ptr;
  289.   int     maxlen;
  290. {
  291.      int n;
  292.      int rc;
  293.      char c;
  294.      
  295.      for (n=1; n < maxlen; n++) {
  296.       if ( (rc = readrecvbuf(fd, &c, 1)) == 1) {
  297.            *ptr++ = c;
  298.            if (c == '\t') {
  299.             *(ptr - 1) = '\0';
  300.             break;
  301.            }
  302.       }
  303.       else if (rc == 0) {
  304.            if (n == 1)
  305.             return(0);    /* EOF, no data read */
  306.            else
  307.             break;        /* EOF, some data was read */
  308.       }
  309.       else
  310.            return(-1);        /* error */
  311.      }
  312.      
  313.      *ptr = 0;                 /* Tack a NULL on the end */
  314.      return(n);
  315. }
  316.  
  317.  
  318. int
  319. sreadword(input, output, maxlen)
  320.   char *input;
  321.   char *output;
  322.   int maxlen;
  323. {
  324.      int n;
  325.      char c;
  326.      
  327.      for (n=0; n < maxlen; n++) {
  328.       c = *input++;
  329.       *output++ = c;
  330.       if (isspace(c)) {
  331.            *(output - 1) = '\0';
  332.            break;
  333.       }
  334.       
  335.       if (c == '\0') {
  336.            break;
  337.       }
  338.      }
  339.      
  340.      *output = '\0';                 /* Tack a NULL on the end */
  341.      return(n);
  342. }
  343.  
  344.  
  345. /*
  346.  * ZapCRLF removes all carriage returns and linefeeds from a C-string.
  347.  */
  348.  
  349. void
  350. ZapCRLF(inputline)
  351.   char *inputline;
  352. {
  353.      char *cp;
  354.  
  355.      cp = strchr(inputline, '\r');    /* Zap CR-LF */
  356.      if (cp != NULL)
  357.       *cp = '\0';
  358.      else {
  359.       cp = strchr(inputline, '\n');
  360.       if (cp != NULL)
  361.            *cp = '\0';
  362.      }
  363. }
  364.  
  365. /*
  366.  *  Utilities for dealing with HTML junk
  367.  */
  368.  
  369. static boolean acceptable[256];
  370. static boolean acceptable_inited = FALSE;
  371.  
  372. void init_acceptable()
  373. {
  374.     unsigned int i;
  375.     char * good = 
  376.       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
  377.     for(i=0; i<256; i++) acceptable[i] = FALSE;
  378.     for(;*good; good++) acceptable[(unsigned int)*good] = TRUE;
  379.     acceptable_inited = TRUE;
  380. }
  381.  
  382. static char hex[17] = "0123456789abcdef";
  383.  
  384. char from_hex(c)
  385.   char c;
  386. {
  387.      return (c>='0')&&(c<='9') ? c-'0'
  388.       : (c>='A')&&(c<='F') ? c-'A'+10
  389.            : (c>='a')&&(c<='f') ? c-'a'+10
  390.             :                      0;
  391. }
  392.  
  393.  
  394. /*
  395.  * Finds out if a character is printable & non white space.
  396.  * if it is, then return a hex encoding of the char,
  397.  * otherwise, just return a reference to the character
  398.  */
  399.  
  400. char *to_hex(c)
  401.   char c;
  402. {
  403.      static char out[4];
  404.  
  405.      if (acceptable_inited == FALSE)
  406.       init_acceptable();
  407.  
  408.      out[0] = '\0';
  409.  
  410.      if (acceptable[(int)c] == TRUE) {
  411.       out[0] = c;
  412.       out[1] = '\0';
  413.      }
  414.      else {
  415.       out[0]='%';
  416.       out[1]=hex[c >> 4];
  417.       out[2]=hex[c & 15];
  418.       out[3]='\0';
  419.      }
  420.  
  421.      return(out);
  422. }
  423.      
  424. /*
  425.  * Replace hex escape sequences with the proper codes...
  426.  *
  427.  * input and output can be the same if you want
  428.  */
  429.  
  430. void
  431. Fromhexstr(input, output)
  432.   char *input, *output;
  433. {
  434.      char c;
  435.      unsigned int b;
  436.  
  437.      while (*input) {
  438.       if (*input == '%') {
  439.            input++;
  440.            c = *input++;
  441.            b = from_hex(c);
  442.            c = *input++;
  443.            if (!c) break;
  444.            *output++ = (b<<4) + from_hex(c);
  445.       }
  446.       else 
  447.            *output++ = *input++;
  448.      }
  449.      *output = '\0';
  450. }
  451.       
  452. void
  453. Tohexstr(input, output)
  454.   char *input, *output;
  455. {
  456.  
  457.      if (acceptable_inited == FALSE)
  458.       init_acceptable();
  459.      
  460.      while (*input) {
  461.  
  462.       if (acceptable[(int)*input] == TRUE) {
  463.            *output++ = *input++;
  464.       }
  465.       else {
  466.            *output++ = '%';
  467.            *output++ = hex[*input >> 4];
  468.            *output++ = hex[*input & 15];
  469.            input++;
  470.       }
  471.      }
  472.  
  473.      *output = '\0';
  474. }
  475.  
  476. /*
  477.  * String insensitive strstr
  478.  */
  479.  
  480. char *
  481. strcasestr(inputline, match)
  482.   char *inputline;
  483.   char *match;
  484. {
  485.      int matchlen=0;
  486.      int i, inlen;
  487.  
  488.      matchlen = strlen(match);
  489.      inlen = strlen(inputline);
  490.  
  491.      for(i=0; i<inlen; i++) {
  492.       if (strncasecmp(inputline+i, match, matchlen)==0)
  493.            return(inputline+i);
  494.      }
  495.  
  496.      return(NULL);
  497. }
  498.  
  499.  
  500. /*
  501.  * Iterate over a string, return a pointer to the next character
  502.  * that isn't whitespace.
  503.  */
  504.  
  505. char *
  506. skip_whitespace(str)
  507.   char *str;
  508. {
  509.      while (isspace(*str) && *str!='\0')
  510.       str++;
  511.  
  512.      return(str);
  513. }
  514.